package ac.github.oa.internal.core.attribute

import ac.github.oa.OriginAttribute
import ac.github.oa.api.event.plugin.AttributeLoadEvent
import ac.github.oa.api.event.plugin.OriginPluginReloadEvent
import org.bukkit.entity.Player
import taboolib.common.LifeCycle
import taboolib.common.io.getInstance
import taboolib.common.io.runningClasses
import taboolib.common.platform.Awake
import taboolib.common.platform.event.SubscribeEvent
import taboolib.common.platform.function.info
import taboolib.module.configuration.Config
import taboolib.module.configuration.Configuration
import java.lang.reflect.Modifier
import java.util.*

object AttributeManager {

    val attributeInstances = mutableListOf<Attribute>()
    val usableAttributes = sortedMapOf<Int, Attribute>()


    val attributeRegistry = mutableListOf<String>()


    @Config("attribute/config.yml")
    lateinit var config: Configuration

    private val table = mutableMapOf<UUID, AttributeData>()

    fun remove(uuid: UUID) {
        table.remove(uuid)
    }

    fun set(uuid: UUID, data: AttributeData) {
        table[uuid] = data
    }

    fun get(player: Player): AttributeData {
        return get(player.uniqueId)
    }

    fun get(uuid: UUID): AttributeData {
        return table[uuid] ?: AttributeData()
    }

    fun getAttribute(clazz: Class<*>): Attribute {
        return attributeInstances.first { it::class.java == clazz }
    }

    fun getAttribute(name: String): Attribute {
        return attributeInstances.first { it.toName() == name }
    }

    fun getAttribute(index: Int): Attribute {
        return usableAttributes.values.first { it.getPriority() == index }
    }

    fun loadAttributeClass() {
        runningClasses.forEach {

            if (Modifier.isInterface(it.modifiers)) return@forEach

            if (Modifier.isAbstract(it.modifiers)) return@forEach

            if (it.isAnnotationPresent(Abstract::class.java)) return@forEach

            if (!Attribute::class.java.isAssignableFrom(it)) return@forEach

            val get = it.getInstance()?.get()

            // 注册object类属性
            if (get != null) {
                registerAttribute(get as Attribute)
            } else {
                registerAttribute(it)
            }

        }
        attributeInstances.forEach {
            loadAttribute(it)
        }
    }

    fun registerAttribute(clazz: Class<*>) {
        registerAttribute(clazz.newInstance() as Attribute)
    }

    fun registerAttribute(attribute: Attribute) {
        attributeInstances += attribute
    }

    fun loadAttribute(attribute: Attribute) {
        val priority = getPriority(attribute)
        if (priority != -1) {
            attribute.setPriority(priority)
            usableAttributes[priority] = attribute
            enableAttribute(attribute)
        }
    }

    @Awake(LifeCycle.ENABLE)
    fun registerAll() {
        this.loadAttributeClass()
    }

    @SubscribeEvent
    fun e(e: OriginPluginReloadEvent) {
        usableAttributes.values.forEach { it.onReload() }
        this.init()
    }

    fun enableAttribute(attribute: Attribute) {
        attribute.onLoad()
    }

    fun getPriority(attribute: Attribute): Int {

        return attributeRegistry.indexOf(attribute.toName())
    }

    @Awake(LifeCycle.ENABLE)
    fun init() {
        attributeRegistry.clear()
        attributeRegistry += OriginAttribute.config.getStringList("attributes")
    }

}
